﻿using System;
using System.Collections.Generic;
using BruteForce.Animation;
using BruteForce.GameObjects;
using BruteForce.NewManagers;
using BruteForce.Screens.PlayingScreen.Map;
using BruteForce.Screens.PlayingScreen.Panels;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;

namespace BruteForce.Characters {
    public struct Key {
        public string Direction;
        public string HumanOrMonster;
        public string Movement;
        public string Type;

        public Key(string p1, string p2, string p3, string p4) {
            HumanOrMonster = p1;
            Type = p2;
            Movement = p3;
            Direction = p4;
        }
    }

    public enum CharacterState {
        PrepareToWalk,
        PrepareToShoot,
        Walking,
        Shooting,
        Idle
    }

    public enum CharacterType {
        Defender, Archer, Bomber, None
    }

    public abstract class Character {
        public static Dictionary<Key, List<Texture2D>> VisualMap = new Dictionary<Key, List<Texture2D>>();
        private readonly GamePanel _gamePanel;
        protected LinearFrameAnimationTransition AnimationTransition;
        public CharacterState CharacterState;
        public Resources CurrentResources;
        public Resources InitialResources;
        public bool IsHuman;
        public MapCell MapCell;
        public CharacterType Type;
        protected LinearMovementTransition WalkingTransition;
        private List<Vector2> _moveVectors;
        public PlayerType BelongsToPlayer;

        protected Character(GamePanel gamePanel, Resources initialResource, Vector2 initialPosition, MapCell mapCell, PlayerType playerType) {
            BelongsToPlayer = playerType;
            InitialResources = initialResource;
            CurrentResources = new Resources(InitialResources);
            _gamePanel = gamePanel;
            WalkingTransition = new LinearMovementTransition(0, initialPosition, initialPosition);
            WalkingTransition.OnTransitionDone += HandleNextWalkingVector;
            CharacterState = CharacterState.Idle;
            MapCell = mapCell;
        }

        public Vector2 DrawOffset {
            get { return new Vector2(-24, -38); }
        }

        public virtual Vector2 PositionInWorld {
            get { return WalkingTransition.CurrentPosition; }
            set {
                WalkingTransition = new LinearMovementTransition(0, value, value);
                WalkingTransition.OnTransitionDone += HandleNextWalkingVector;
            }
        }


        public virtual Texture2D Texture {
            get { return AnimationTransition.CurrentTexture; }
        }

        public float DrawDepth { get; set; }

        private void HandleNextWalkingVector() {
            _gamePanel.UpdateCharacterCellLocation(this);
            if (_moveVectors.Count > 0) {
                Vector2 mv = _moveVectors[0];
                _moveVectors.RemoveAt(0);
                _MoveTo(mv);
            } else {
                this.CharacterState = CharacterState.Idle;
            }
        }


        public void UpdateTileLocation(TileMap myMap) {
            if (MapCell != null) {
                MapCell.CharacterInCell = null;
            }
            MapCell cell = myMap.GetCellAtWorldPoint(PositionInWorld);
            MapCell = cell;
            cell.CharacterInCell = this;
        }

        public static void LoadContent(ContentManager content) {
            var humanOrMonster = new List<string>(new[] { "Humans", "Monsters" });
            var type = new List<string>(new[] { "Archer", "Bomber", "Defender" });
            var archerMovement = new List<string>(new[] { "been hit", "running", "walking", "shooting", "talking" });
            var defenderMovement = new List<string>(new[] { "been hit", "walking", "attack", "talking" });
            var bomberMovement = new List<string>(new[] { "walking" });
            var direction = new List<string>(new[] { "sw", "se", "nw", "ne" });

            foreach (string h in humanOrMonster) {
                foreach (string t in type) {
                    foreach (string d in direction) {
                        if (t == "Archer") {
                            foreach (string m in archerMovement) {
                                VisualMap.Add(new Key(h, t, m, d), new List<Texture2D>());
                            }
                        }
                        if (t == "Bomber") {
                            foreach (string m in bomberMovement) {
                                VisualMap.Add(new Key(h, t, m, d), new List<Texture2D>());
                            }
                        }
                        if (t == "Defender") {
                            foreach (string m in defenderMovement) {
                                VisualMap.Add(new Key(h, t, m, d), new List<Texture2D>());
                            }
                        }
                    }
                }
            }


            foreach (Key v in VisualMap.Keys) {
                int i = 0;
                try {
                    while (true) {
                        string fileName = "Characters/" + v.HumanOrMonster + "/" + v.Type + "/" + v.Movement + " " +
                                          v.Direction + "000" + i;
                        VisualMap[v].Add(content.Load<Texture2D>(fileName));
                        i++;
                    }
                } catch (ContentLoadException exception) {
                }
            }
        }

        public void MoveTo(List<Vector2> worldLocations) {
            //Console.WriteLine("Path movement! " + worldLocations);
            if (worldLocations.Count > 0) worldLocations.RemoveAt(0);
            _moveVectors = worldLocations;
            HandleNextWalkingVector();
        }

        private void _MoveTo(Vector2 worldPosition) {
            Console.WriteLine("Instructed to move to " + worldPosition + " from " + PositionInWorld);
            WalkingTransition.StartPosition = PositionInWorld;
            WalkingTransition.EndPosition = worldPosition;
            WalkingTransition.Duration = 0.5;
            WalkingTransition.StartTransition();
            AnimationTransition.Textures =
                VisualMap[new Key((IsHuman ? "Humans" : "Monsters"), Type.ToString(), "walking", FindDirections())];
            AnimationTransition.TextureSwitchDuration = 0.09;
            AnimationTransition.StartTransition();
            AnimationTransition.Duration = 0.5;
        }

        protected string FindDirections() {
            string ans;
            if (WalkingTransition.StartPosition.Y > WalkingTransition.EndPosition.Y) ans = "n";
            else ans = "s";

            if (WalkingTransition.StartPosition.X > WalkingTransition.EndPosition.X) ans += "w";
            else ans += "e";
            return ans;
        }

        protected string FindDirections(Vector2 worldPosition) {
            string ans;
            if (WalkingTransition.StartPosition.Y > worldPosition.Y) ans = "n";
            else ans = "s";

            if (WalkingTransition.StartPosition.X > worldPosition.X) ans += "w";
            else ans += "e";
            return ans;
        }

        private string FindOpositeDirections(Vector2 startPos) {
            string ans;
            if (WalkingTransition.EndPosition.Y > startPos.Y) ans = "n";
            else ans = "s";

            if (WalkingTransition.EndPosition.X > startPos.X) ans += "w";
            else ans += "e";
            return ans;
        }

        public virtual void BeenShot(Vector2 startPos) {
//            Console.WriteLine(Type.ToString());
//            Console.WriteLine(FindOpositeDirections(startPos));
            AnimationTransition.Textures =
                VisualMap[
                    new Key((IsHuman ? "Humans" : "Monsters"), Type.ToString(), "been hit",
                            FindOpositeDirections(startPos))];

            AnimationTransition.TextureSwitchDuration = 0.15;
            AnimationTransition.StartTransition();
            AnimationTransition.Duration = 1;
            AnimationTransition.OnTransitionDone += AnimationTransitionDone;
        }



        private void AnimationTransitionDone() {
//            if (InitialResources.Life <= 0) {
//                GamePanel.Current.RemoveCharacter(this);
//            }
            DecreaseLife(GamePanel.Current.lastShotPower);
        }

        public void DecreaseLife(int lifeAmount) {
            InitialResources.Life -=lifeAmount;
            if (InitialResources.Life <= 0) {
                if (BelongsToPlayer == PlayerType.Human) {
                    PlayerManager.Instance.HumanPlayer.RemoveGamePiece(this);
                } else {
                    PlayerManager.Instance.MonsterPlayer.RemoveGamePiece(this);
                }
                GamePanel.Current.RemoveCharacter(this);

                PlayerManager.Instance.GetPlayer(BelongsToPlayer).CheckIfLost();
            }
        }

        public void DecreseTurnSpeed(int distanceTraveled) {
            CurrentResources.Speed -= distanceTraveled;
        }
          
        public void InitTurn() {
            CurrentResources = new Resources(InitialResources);
        }
    }
}